home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 8
/
QRZ Ham Radio Callsign Database - Volume 8.iso
/
pc
/
files
/
t_jnos
/
j109lxa4.tgz
/
j109lxa4.tar
/
cmdparse.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-04
|
10KB
|
502 lines
/* Parse command line, set up command arguments Unix-style, and call function.
* Note: argument is modified (delimiters are overwritten with nulls)
*
* Copyright 1991 Phil Karn, KA9Q
*
* Improved error handling by Brian Boesch of Stanford University
* Feb '91 - Bill Simpson
* bit16cmd for PPP
* Mar '91 - Glenn McGregor
* handle string escaped sequences
*/
#include <stdio.h>
#include <ctype.h>
#ifdef MSDOS
#include <conio.h>
#endif
#include "global.h"
#include "config.h"
#include "proc.h"
#include "cmdparse.h"
#include "session.h"
#include "pktdrvr.h"
#include "iface.h"
#include "socket.h"
struct boolcmd {
char *str; /* Token */
int val; /* Value */
};
static struct boolcmd Boolcmds[] = {
"y", 1, /* Synonyms for "true" */
"yes", 1,
"true", 1,
"on", 1,
"1", 1,
"set", 1,
"enable", 1,
"n", 0, /* Synonyms for "false" */
"no", 0,
"false", 0,
"off", 0,
"0", 0,
"clear", 0,
"disable", 0,
NULLCHAR
};
static char *stringparse __ARGS((char *line));
static char *
stringparse(line)
char *line;
{
register char *cp = line;
unsigned long num;
while ( *line != '\0' && *line != '\"' ) {
if ( *line == '\\' ) {
line++;
switch ( *line++ ) {
case 'n':
*cp++ = '\n';
break;
case 't':
*cp++ = '\t';
break;
case 'v':
*cp++ = '\v';
break;
case 'b':
*cp++ = '\b';
break;
case 'r':
*cp++ = '\r';
break;
case 'f':
*cp++ = '\f';
break;
case 'a':
#ifdef __STDC__
*cp++ = '\a';
#else
*cp++ = '\007';
#endif
break;
case '\\':
*cp++ = '\\';
break;
case '\?':
*cp++ = '\?';
break;
case '\'':
*cp++ = '\'';
break;
case '\"':
*cp++ = '\"';
break;
case 'x':
num = strtoul( --line, &line, 16 );
*cp++ = (char) num;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
num = strtoul( --line, &line, 8 );
*cp++ = (char) num;
break;
case '\0':
return NULLCHAR;
default:
*cp++ = *(line - 1);
break;
};
} else {
*cp++ = *line++;
}
}
if ( *line == '\"' )
line++; /* skip final quote */
*cp = '\0'; /* terminate string */
return line;
}
#ifdef LOCK
int Kblocked;
char *Kbpasswd;
#endif
int
cmdparse(cmds,line,p)
struct cmds cmds[];
register char *line;
void *p;
{
struct cmds *cmdp;
char *argv[NARG],*cp;
char **pargv;
int argc,i;
/* Remove cr/lf */
rip(line);
for(argc = 0;argc < NARG;argc++)
argv[argc] = NULLCHAR;
for(argc = 0;argc < NARG;){
register int qflag = FALSE;
/* Skip leading white space */
while(*line == ' ' || *line == '\t')
line++;
if(*line == '\0')
break;
/* return if comment character first non-white */
if ( argc == 0 && *line == '#' )
return 0;
/* Check for quoted token */
if(*line == '"'){
line++; /* Suppress quote */
qflag = TRUE;
}
argv[argc++] = line; /* Beginning of token */
if(qflag){
/* Find terminating delimiter */
if((line = stringparse(line)) == NULLCHAR){
return -1;
}
} else {
/* Find space or tab. If not present,
* then we've already found the last
* token.
*/
#ifdef old
if((cp = strchr(line,' ')) == NULLCHAR
&& (cp = strchr(line,'\t')) == NULLCHAR){
break;
}
#endif
for(cp=line;*cp;cp++) {
if(*cp == ' ' || *cp == '\t')
break;
}
/* if we didn't reach end of line yet, cutoff this arg here */
if(*cp == '\0')
break;
*cp++ = '\0';
line = cp;
}
}
if (argc < 1) { /* empty command line */
argc = 1;
argv[0] = "";
}
#ifdef LOCK
/* Check to see if this is the Command session.
* If so, check to see if the keyboard is locked
* Added 12/12/91 WG7J
*/
if(Curproc->input == Command->input)
if(Kblocked) { /*check argv[0] for password!*/
if(strcmp(argv[0],Kbpasswd)) {
tputs("\nKeyboard remains locked\n");
return 0;
}
Command->ttystate.echo = 1; /* turn character echo back on ! */
Kblocked=0; /* correct password, so unlock */
return 0;
}
#endif
/* Look up command in table; prefix matches are OK */
/* Not case sensitive anymore - WG7J */
for(cmdp = cmds;cmdp->name != NULLCHAR;cmdp++){
if(strncmpi(argv[0],cmdp->name,strlen(argv[0])) == 0)
break;
}
if(cmdp->name == NULLCHAR) {
if(cmdp->argc_errmsg != NULLCHAR)
tprintf("%s\n",cmdp->argc_errmsg);
return -1;
} else {
if(argc < cmdp->argcmin) {
/* Insufficient arguments */
tprintf("Usage: %s\n",cmdp->argc_errmsg);
return -1;
} else {
if(cmdp->stksize == 0){
return (*cmdp->func)(argc,argv,p);
} else {
/* Make private copy of argv and args,
* spawn off subprocess and return.
*/
pargv = (char **)callocw((unsigned)argc,sizeof(char *));
for(i=0;i<argc;i++)
pargv[i] = strdup(argv[i]);
newproc(cmdp->name,(unsigned)cmdp->stksize,
(void (*)__ARGS((int,void*,void*)))cmdp->func,argc,pargv,p,1);
return(0);
}
}
}
}
/* Call a subcommand based on the first token in an already-parsed line */
int
subcmd(tab,argc,argv,p)
struct cmds tab[];
int argc;
char *argv[];
void *p;
{
register struct cmds *cmdp;
char **pargv;
int found = 0;
int i;
/* Strip off first token and pass rest of line to subcommand */
if (argc < 2) {
if (argc < 1)
tprintf("SUBCMD - Don't know what to do?\n");
else
tprintf("\"%s\" - takes at least one argument\n",argv[0]);
return -1;
}
argc--;
argv++;
for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
/* Not case sensitive anymore - WG7J */
if(strncmpi(argv[0],cmdp->name,strlen(argv[0])) == 0){
found = 1;
break;
}
}
if(!found){
tprintf("valid subcommands:");
for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++)
if(tprintf(" %s",cmdp->name) == EOF)
return -1;
tprintf("\n");
return -1;
}
if(argc < cmdp->argcmin){
if(cmdp->argc_errmsg != NULLCHAR)
tprintf("Usage: %s\n",cmdp->argc_errmsg);
return -1;
}
if(cmdp->stksize == 0){
return (*cmdp->func)(argc,argv,p);
} else {
/* Make private copy of argv and args */
pargv = (char **)callocw((unsigned)argc,sizeof(char *));
for(i=0;i<argc;i++)
pargv[i] = strdup(argv[i]);
newproc(cmdp->name,(unsigned)cmdp->stksize,
(void (*)__ARGS((int,void*,void*)))cmdp->func,argc,pargv,p,1);
return(0);
}
}
/* Subroutine for setting and displaying boolean flags */
int
setbool(var,label,argc,argv)
int *var;
char *label;
int argc;
char *argv[];
{
struct boolcmd *bc;
if(argc < 2){
tprintf("%s: %s\n",label,*var ? "on":"off");
return 1;
}
for(bc = Boolcmds;bc->str != NULLCHAR;bc++){
if(strcmpi(argv[1],bc->str) == 0){
*var = bc->val;
return 0;
}
}
tprintf("Valid options:");
for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
if(tprintf(" %s",bc->str) == EOF)
return 1;
tprintf("\n");
return 1;
}
/* Subroutine for setting and displaying bit values */
int
bit16cmd(bits,mask,label,argc,argv)
int16 *bits;
int16 mask;
char *label;
int argc;
char *argv[];
{
int doing = (*bits & mask);
int result = setbool( &doing, label, argc, argv );
if ( !result ) {
if ( doing )
*bits |= mask;
else
*bits &= ~mask;
}
return result;
}
/* Subroutine for setting and displaying long variables */
int
setlong(var,label,argc,argv)
long *var;
char *label;
int argc;
char *argv[];
{
if(argc < 2){
tprintf("%s: %ld\n",label,*var);
return 1;
} else {
*var = atol(argv[1]);
return 0;
}
}
/* Subroutine for setting and displaying short variables */
int
setshort(var,label,argc,argv)
unsigned short *var;
char *label;
int argc;
char *argv[];
{
if(argc < 2){
tprintf("%s: %u\n",label,*var);
return 1;
} else {
*var = atoi(argv[1]);
return 0;
}
}
/* Subroutine for setting and displaying integer variables */
int
setint(var,label,argc,argv)
int *var;
char *label;
int argc;
char *argv[];
{
if(argc < 2){
tprintf("%s: %i\n",label,*var);
return 1;
} else {
*var = atoi(argv[1]);
return 0;
}
}
/* Subroutine for setting and displaying unsigned integer variables */
int
setuns(var,label,argc,argv)
unsigned *var;
char *label;
int argc;
char *argv[];
{
if(argc < 2){
tprintf("%s: %u\n",label,*var);
return 1;
} else {
*var = atoi(argv[1]);
return 0;
}
}
/* Subroutine for setting and displaying int variables (with range check) */
int
setintrc(var, label, argc, argv, minval, maxval)
int16 *var;
char *label;
int argc;
char *argv[];
int minval;
int16 maxval;
{
int tmp;
if (argc < 2)
tprintf("%s: %u\n", label, *var);
else {
tmp = atoi(argv[1]);
if (isalpha(*argv[1]) || tmp < minval || tmp > maxval) {
tprintf("%s must be %i..%i\n", label, minval, maxval);
return 1;
}
*var = (int16)tmp;
}
return 0;
}
/* Set flags on ax.25 interfaces - WG7J */
int setflag(int argc,char *ifname,long flag,char *cmd) {
struct iface *ifp;
struct boolcmd *bc;
if(argc == 1) {
for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
if(ifp->flags & flag)
tprintf("%s\n",ifp->name);
} else {
if((ifp = if_lookup(ifname)) == NULLIF){
tprintf(Badinterface,ifname);
return 1;
}
/*
if(ifp->type != CL_AX25) {
tputs("not an AX.25 interface\n");
return 1;
}
*/
if(argc == 2) {
/* Show the value of the flag */
if(ifp->flags & flag)
tputs("On\n");
else
tputs("Off\n");
} else {
for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
if(strcmpi(cmd,bc->str) == 0){
if(bc->val)
ifp->flags |= flag;
else
ifp->flags &= ~flag;
return 0;
}
/* Invalid option ! */
tputs("Valid options:");
for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
if(tprintf(" %s",bc->str) == EOF)
return 1;
tputc('\n');
}
}
return 0;
}